讓我們把焦點從流程的部分轉回應用程式上,現在第二頁面還缺少一個下一步的按鈕,同時得做一些邏輯驗證,首先在版面上新增一個按鈕及程式上加入點擊的監聽,這些相信難不倒已經學習過之前章節的讀者。
接著使用 arrayListOf
盛裝,自三個 switch (北極、南極、芬蘭) 讀取的選擇狀態,到這邊可以先試試看使用 println(answer)
查看內容物,接著再使用 lambda
設計我們需要的邏輯:三個至少要選一個。
這裡使用 any
去判斷集合中是否有任何 true
值,Line: 28 的寫法是 Line: 29 的簡化版,在先前的 Day 11 有相關說明,各位應該可以感覺到,簡化前後以第一直覺去看該行程式碼,哪一段比較能快速理解邏輯條件;又哪一段撰寫起來較迅速簡潔。但是 IDE 會提示你簡化,受不了那條線一直出現在那邊的人應該不少...,採用簡化版本再搭配註解也是個不錯的辦法。
以下是上圖程式執行成果,在沒選擇的狀況下點按鈕後印出的結果,讀者也可以試試看任選項目後會有什麼不同:
I/System.out: [false, false, false]
false
false
接著把第三頁面加入應用程式中,並且完成邏輯判斷式,可以利用 Toast.makeText()
方法,顯示訊息到螢幕上呈現,第一個參數傳入目前頁面,使用關鍵字 this
即可,第二參數放入想要顯示的文字,如同先前課程提到的,應該採用文字資源管理的方式實作,在這邊的示範為了方便就直接放入文字,第三參數可決定訊息顯示持續的時間,有 Toast.LENGTH_SHORT
、Toast.LENGTH_LONG
兩種可以選擇,分別是 2 秒與 3.5 秒的差別。
執行結果如下:
接著會有一個問題:第三頁面要怎麼知道在第二頁面的選項呢?我們必須設計一個機制將第二頁的值傳送過去,使用 xxx.putExtra()
方法,其中 xxx 是目標頁面,putExtra
可以放入許多型態的資料,這邊我們先用純文字示範。
putExtra()
第一個參數要指定一個 ID,做為取值時的識別,在這邊使用常數的定義方式,讓我們先命名 (規則:全部大寫,以 EXTRA_ 開頭,後面根據常數用途決定)。
暫時是紅字沒關係,接著到專案總管上新增一個新的 Kotlin File/Class。
新增的檔案命名為:ExtraConstants,用來存放所有的 ID,方便管理。
在新檔案中加入常數字串變數,字串內容也是依據用途決定,只要不重複即可。
此時回到第二頁面就能看到紅字錯誤提示已經消失,接著切換到第三頁面,使用 intent.getStringExtra()
取得剛剛傳入的值,不同的形態會有不一樣的提取使用方法,接著用剛剛介紹過的 Toast
將內容顯示在螢幕上。
成功!正確無誤。
但我們的程式是一個 List
型態,要如何傳遞呢?首先必須將整個集合序列化 (Serializable) 轉成 Bundle()
的型態,再將此物件傳送。 Serializable 有其效能上的缺點,文章後段會說明
val extra = Bundle()
extra.putSerializable(EXTRA_AURORA_LIST, answerList)
thirdActivity.putExtra(EXTRA_AURORA_LIST, extra)
另一個頁面接收時,反向處理,先取出 Bundle
型態,再將之解序列化,並轉型回 ArrayList<Boolean>
格式,讀者可以試著使用 println
印出結果。
var auroraList = intent.getBundleExtra(EXTRA_AURORA_LIST).getSerializable(EXTRA_AURORA_LIST) as ArrayList<Boolean>
println(auroraList)
在 Run 視窗中,println
出來的值是:I/System.out: [false, true, false]
,這樣的格式有個缺點:不知道選項到底代表什麼,若要處理這個問題,可以將 arrayList
改為使用 hashMap
,所有相關程式調整幅度不大,只有三個地方需要修改,請查看下列兩張截圖的紅框處。
修改後可以看到 println
的結果變成:I/System.out: {Arctic=false, Antarctic=true, Finland=true}
,對於後續使用上會比較方便。另外 Serializable
的效能表現其實是有問題的,可以參考這篇文章的比較。
圖片來源:https://android.jlelse.eu/parcelable-vs-serializable-6a2556d51538
在明天的章節會介紹改用 Parcelable
方式,搭配使用之前提過的 data class
來進行資料傳遞的乘載。
額外討論:在所有教學中有用過三種按鈕設定監聽點擊的方法,各位覺得在實作上有什麼優缺點的不同?歡迎大家提出自己的看法,以及會選擇的是哪一個方式。
// 第一種:直接在 onCreate 完成
goBtn.setOnClickListener {
// Do something
}
// 第二種:透過 layout.xml 鏈結
fun backBtnOnClick(view: View) {
// Do something
}
// 第三種:在 onCreate 設定一行監聽,呼叫另外獨立的方法
nextBtn.setOnClickListener{ nextBtnOnClick() }
fun nextBtnOnClick() {
// Do something
}
那麼今天的教學就到這邊,我們明天見!
資料參考
Toast length long and short 差異
https://stackoverflow.com/questions/7965135/what-is-the-duration-of-a-toast-length-long-and-length-shortIntent putExtra 用於集合
https://stackoverflow.com/questions/18050030/intent-putextra-arraylistnamevaluepairParcelable vs Serializable
https://android.jlelse.eu/parcelable-vs-serializable-6a2556d51538Activity-Android Developers (中文)
https://developer.android.com/guide/components/activities?hl=zh-twKotlin for Android: Beginner to Advanced | Udemy
https://www.udemy.com/devslopes-android-kotlin/